class BlueBall:
    def __init__(self, latest_red_tuple, latest_5_blue_tuple):
        self.latest_red_tuple = latest_red_tuple  # 当期的红球元组
        self.latest_5_blue_tuple = latest_5_blue_tuple  # 最近五期的篮球元组

    def get_blue_num_range(self):
        # 列出近5期的蓝球号码，先将这5个号码相加，计算其平均值，然后把平均值加4和减4
        sum_num = sum(self.latest_5_blue_tuple)
        avg = round(sum_num / len(self.latest_5_blue_tuple))
        range_set = set(range(avg - 4, avg + 4 + 1))
        return range_set

    def divide_3_get_mod_set(self):
        curr_num = self.latest_5_blue_tuple[-1]  # 当期篮球号码
        # 除3余0包括3、6、9、12、15；除3余1包括1、4、7、10、13、16；除3余2包括2、5、8、11、14。
        three_dict = {
            0: {3, 6, 9, 12, 15},
            1: {1, 4, 7, 10, 13, 16},
            2: {2, 5, 8, 11, 14}
        }
        result = curr_num % 3  # 除3取余
        # 得到集合
        result_set = three_dict.get(result)
        blue_range_set = self.get_blue_num_range()  # 篮球的取值范围
        # 取并集
        temp_set = result_set | blue_range_set
        # 如果是空,就直接返回取余法的集合,不为空,就返回交集
        if len(temp_set) == 0:
            return result_set
        else:
            return temp_set

    def remove_blue_num(self):
        # 排除篮球号码
        blue_ball_num_set = self.divide_3_get_mod_set()
        # 每期开奖的最大红球号码减去当期蓝号的差为下期所要排除的蓝球号码
        curr_blue_num = self.latest_5_blue_tuple[-1]
        need_remove_num1 = max(self.latest_red_tuple) - curr_blue_num
        if need_remove_num1 in blue_ball_num_set:
            blue_ball_num_set.remove(need_remove_num1)
        # 两期蓝号进行相加，二者之和减去最大蓝号为下期所要排除的蓝号
        before_blue_num = self.latest_5_blue_tuple[-2]
        need_remove_num2 = curr_blue_num + before_blue_num - max(curr_blue_num, before_blue_num)
        if need_remove_num2 in blue_ball_num_set:
            blue_ball_num_set.remove(need_remove_num2)
        # 利用当期期数尾排除当期的同尾蓝号
        curr_blue_num_tail = int(str(curr_blue_num)[-1:])
        if curr_blue_num_tail in blue_ball_num_set:
            blue_ball_num_set.remove(curr_blue_num_tail)
        # 连续两期蓝号进行相减(最大蓝号—最小蓝号)，二者之间的差为下期排除的蓝号
        if abs(curr_blue_num - before_blue_num) in blue_ball_num_set:
            blue_ball_num_set.remove(abs(curr_blue_num - before_blue_num))
        # 每期开奖的红球由小到大依次相加，其相加结果以最接近最大蓝号为界线，所得到的和数为下期需要排除的蓝号
        temp_list = list(self.latest_red_tuple)
        sorted(temp_list)
        temp_sum = 0
        for i in temp_list:
            if temp_sum + i > 16:
                break
            temp_sum += i
        if temp_sum in blue_ball_num_set:
            blue_ball_num_set.remove(temp_sum)

        # 将元组中的所有数相加,如果不大于16,则追加到元组
        if sum(blue_ball_num_set) <= 16:
            blue_ball_num_list = list(blue_ball_num_set)
            blue_ball_num_list.append(sum(blue_ball_num_set))
            blue_ball_num_set = set(blue_ball_num_list)
        return blue_ball_num_set

    def get_next_blue_ball_num_set(self):
        """
        获取预测的篮球号码集合
        :return: 篮球号码集合
        """
        return self.remove_blue_num()

    def __str__(self):
        return "蓝球类: " + str(self.latest_red_tuple) + "---" + str(self.latest_5_blue_tuple)
